package ReflectionTest;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

class Person {
    private String name;
    int age;
    public int id;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return getClass().getName() + " [name=" + name + ", age=" + age + "] from InnerStruct";
    }

    public void show() throws NullPointerException, ClassCastException {
        System.out.println("I am a person.");
    }

    private void display(String nation) {
        System.out.println("My nation is " + nation);
    }
}

public class ClassInnerStructTest {
    public static void main(String[] args) throws Exception {
        Class<Person> personClass = Person.class;

        // 类的信息
        System.out.println("类的全限定名：" + personClass.getName());
        System.out.println("类的简单名：" + personClass.getSimpleName());
        System.out.println("类的权限修饰符：" + personClass.getModifiers());
        System.out.println("类的包名：" + personClass.getPackage().getName());
        System.out.println("类的注解：" + personClass.getAnnotations());
        System.out.println("类的父类：" + personClass.getSuperclass().getName());
        System.out.println("类的带泛型类型的父类：" + personClass.getGenericSuperclass());
        System.out.println("类的接口：" + personClass.getInterfaces());

        // 类的构造器
        System.out.println("类的构造器：");
        for (var constructor : personClass.getDeclaredConstructors()) {
            System.out.println(constructor);
        }

        // 类的属性
        System.out.println("类的属性：");
        Person person = new Person("Tom", 18);
        Field[] fields = personClass.getDeclaredFields();
        for (Field field : fields) {
            System.out.println("-------- 当前属性：" + field.getName() + " --------");
            field.setAccessible(true);
            System.out.println("属性名：" + field.getName());
            System.out.println("属性数据类型：" + field.getType());
            System.out.println("属性实例的值：" + field.get(person));
            System.out.println("属性修饰符：" + field.getModifiers());
            System.out.println("属性注解：" + field.getAnnotations());
            System.out.println("属性泛型类型：" + field.getGenericType());
            System.out.println("属性声明类：" + field.getDeclaringClass());
        }
        // 类属性的操作
        Field idField = personClass.getDeclaredField("id");
        idField.set(person, 1001); // 设置属性值
        idField.setAccessible(true); // 设置为可访问
        System.out.println("修改后的属性值：" + idField.get(person)); // 获取属性值

        // 类的方法
        System.out.println("类的方法：");
        // Method[] methods = personClass.getMethods(); // 获取当前运行时类及其父类中声明为public的方法
        Method[] methods = personClass.getDeclaredMethods(); // 获取当前运行时类中声明的所有方法
        for (Method method : methods) {
            System.out.println("-------- 当前方法：" + method.getName() + " --------");
            System.out.println("方法泛型类型：" + method.getGenericReturnType());
            System.out.println("方法修饰符：" + method.getModifiers());
            System.out.print("方法注解：");
            for (var annotation : method.getAnnotations()) {
                System.out.print(annotation + " ");
            }

            System.out.println();
            System.out.println("方法名：" + method.getName());
            System.out.println("方法返回类型：" + method.getReturnType().getName());
            System.out.println("方法参数个数：" + method.getParameterCount());
            System.out.print("方法参数类型：");
            for (var parameterType : method.getParameterTypes()) {
                System.out.print(parameterType.getName() + " ");
            }
            System.out.println();
            System.out.print("方法异常类型：");
            for (var exceptionType : method.getExceptionTypes()) {
                System.out.print(exceptionType.getName() + " ");
            }
            System.out.println();
            System.out.println("方法声明类：" + method.getDeclaringClass());
        }
        // 类方法的操作
        Method showMethod = personClass.getDeclaredMethod("show");
        showMethod.setAccessible(true); // 设置为可访问
        showMethod.invoke(person); // 调用方法，返回值为方法的返回值
        Method displayMethod = personClass.getDeclaredMethod("display", String.class); // 带参数的方法
        displayMethod.setAccessible(true); // 设置为可访问
        displayMethod.invoke(person, "China"); // 调用方法，返回值为方法的返回值
    }
}
